﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum Skills
{
    Move,
    AutoMove,
    K_Dash,
    K_HeaveyAttack,
    M_Shot,
    SlimeAttack,
    ManaRecovery,
}
public enum States
{
    StandState,
    MoveState,
    K_DashState,
    K_HeaveyAttackState,
    SlimeAttackState,
}
public enum Job
{
    Knight,
    Mage,
    Ranger,
}
public class EntityBase : BaseBehaviour, ISerializationCallbackReceiver
{
    /// <summary>
    /// 基本参数
    /// </summary>
    public MonoParameter parameter;

    /// <summary>
    /// 状态机参数
    /// </summary>
    public Istates currentState;
    public Dictionary<States, Istates> states = new Dictionary<States, Istates>();

    /// <summary>
    /// 拥有状态的技能
    /// </summary>
    public static Dictionary<Skills, States> skillAndState = new Dictionary<Skills, States>()
    {
        {Skills.Move, States.MoveState},
        {Skills.AutoMove, States.MoveState},
        {Skills.K_Dash, States.K_DashState},
        {Skills.K_HeaveyAttack, States.K_HeaveyAttackState },
        {Skills.SlimeAttack, States.SlimeAttackState },
    };

    /// <summary>
    /// 当前状态可使用的技能
    /// </summary>
    public static Dictionary<States, List<Skills>> ableToUseSkillList = new Dictionary<States, List<Skills>>
    {
        {States.StandState, new List<Skills>
            {
            Skills.Move,
            Skills.K_Dash,
            Skills.K_HeaveyAttack,
            Skills.M_Shot,
            Skills.AutoMove,
            Skills.SlimeAttack,
            }
        },
        {States.MoveState, new List<Skills>
            {
            Skills.Move,
            Skills.K_Dash,
            Skills.K_HeaveyAttack,
            Skills.M_Shot,
            Skills.AutoMove,
            Skills.SlimeAttack,
            }
        },
        {States.K_DashState, new List<Skills>
            {
            }
        },
        {States.K_HeaveyAttackState, new List<Skills>
            {
                Skills.K_Dash,
            }
        },
        {States.SlimeAttackState, new List<Skills>
            {
                
            }
        }
    };

    /// <summary>
    /// 技能列表
    /// </summary>
    public Dictionary<Skills, SkillBase> skillList = new Dictionary<Skills, SkillBase>();

    /// <summary>
    /// 序列化用
    /// </summary>
    public List<Skills> skillname = new List<Skills>();
    public List<SkillBase> _skillList = new List<SkillBase>();
    public List<States> _states = new List<States>();

    /// <summary>
    /// 职业
    /// </summary>
    public string job;

    public void Init(string job)
    {
        //生命值初始化
        parameter.HealthData.maxHealth = 100;
        parameter.HealthData.currentHealth = parameter.HealthData.maxHealth;
        //蓝量初始化
        parameter.ManaData.maxMana = 100;
        parameter.ManaData.currentMana = parameter.ManaData.maxMana;
        parameter.ManaData.manaRecoverySpeed = 0.01f;
        //注册组件
        //parameter.ComponentData.rb = this.GetComponent<RigidbodyTimeline2D>();
        parameter.ComponentData.animator = this.GetComponent<Animator>();
        parameter.ComponentData.transform = this.transform;
        //注册editor中的技能
        AddSkillInEditor();
        //根据职业注册技能及状态机
        AddState(States.StandState, new StandState(this));
        
        ChangeState(States.StandState);

        //test

    }

    public virtual void Update()
    {
        HpCheck();
        currentState.OnUpdate();
    }

    public void AddState(States stateName, Istates state)
    {
        states.Add(stateName, state);
    }

    /// <summary>
    /// 添加技能和配套的状态机（如有）
    /// </summary>
    /// <param name="skillName"></param>
    /// <param name="newSkill"></param>
    public void AddSkill(Skills skillName, SkillBase newSkill, EntityBase user)
    {
        if(!skillList.ContainsKey(skillName))
        {
            skillList.Add(skillName, newSkill);
            skillList[skillName].Init(user);
        }
        if(skillAndState.ContainsKey(skillName))
        {
            foreach(var t in typeof(Istates).Assembly.GetTypes())
            {
                if(typeof(Istates).IsAssignableFrom(t) &&  !t.IsAbstract && t.Name == skillAndState[skillName].ToString())
                {
                    AddState(skillAndState[skillName], (Istates)Activator.CreateInstance(t,1,this));
                    
                }
            }
        }
    }

    public void AddSkillInEditor()
    {
        foreach (Skills skill in skillname)
        {
            foreach (var t in typeof(SkillBase).Assembly.GetTypes())
            {
                if (t.IsSubclassOf(typeof(SkillBase)) && !t.IsAbstract && t.Name == skill.ToString())
                {                    
                    AddSkill(skill, (SkillBase)ScriptableObject.CreateInstance(t), this);
                }
            }
        }
    }

    public void UpdateAllSkills()
    {
        //Debug.Log("running");

        foreach (KeyValuePair<Skills, SkillBase> skill in skillList)
        {
            if(skill.Value.skillType == SkillType.Passive)
            {
                skill.Value.FixedUpdate();
            }else
            if (ableToUseSkillList[currentStateToEnum()].Contains(skill.Key))
            {
                skill.Value.FixedUpdate();
            }

            //Debug.Log("use all skill");
        }
    }

    public void GetMousePos()
    {
        var screenPos = Camera.main.WorldToScreenPoint(transform.position);
        var mousePos = Input.mousePosition;
        mousePos.z = screenPos.z;
        var mousePosInWorld = Camera.main.ScreenToWorldPoint(mousePos);


        parameter.AimData.aimDir = (mousePosInWorld - transform.position).normalized;
    }

    public void GetTarget()
    {
        if(parameter.AimData.target == null)
        {
            try
            {
                parameter.AimData.target = GameObject.FindGameObjectWithTag("Player").gameObject.transform;
            }catch
            {

            }
            
        }else
        {
            parameter.AimData.distance = (parameter.AimData.target.position - transform.position).magnitude;
            parameter.AimData.aimDir = (parameter.AimData.target.position - transform.position).normalized;
        }
        
    }

    public void ChangeState(States state)
    {
        if (currentState != states[state])
        {
            if (currentState != null)
            {
                currentState.OnExit();
            }
            currentState = states[state];
            currentState.OnEnter();
        }

    }

    public States currentStateToEnum()
    {
        var state = States.StandState;
        foreach (KeyValuePair<States, Istates> pair in states)
        {
            if (pair.Value == currentState)
            {
                state = pair.Key;
            }
        }
        return state;
    }

    


    public float HpCheck()
    {
        var hp = parameter.HealthData.currentHealth;
        if (hp <= 0)
        {
            Die();
            //GameObject.Destroy(this.gameObject);
        }
        return hp;
    }

    public virtual void Die()
    {

    }
    
    public void OnBeforeSerialize()
    {
        //_key.Clear();
        _skillList.Clear();
        _states.Clear();

        foreach (var kvp in skillList)
        {
            //_key.Add(kvp.Key);
            _skillList.Add(kvp.Value);
        }
        foreach (var kvp in states)
        {
            _states.Add(kvp.Key);
        }
    }
    public void OnAfterDeserialize()
    {
        //skillList = new Dictionary<Skills, SkillBase>();
        //
        //for (int i = 0; i != Math.Min(_key.Count, _values.Count); i++)
        //    skillList.Add(_key[i], _values[i]);
    }
    void OnGUI()
    {
        //foreach (var kvp in _values)
        //    GUILayout.Label( " value: " + kvp);
    }

    


}
